﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using DiscoveryLogic.Analytics.BusinessLogic;
using DiscoveryLogic.Analytics.BusinessLogic.Measures;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.DataObjects.Filters;
using DiscoveryLogic.Analytics.DataObjects.Measures;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Analytics.DataObjects.Visuals;
using DiscoveryLogic.Analytics.Modules.Diagrams.Renders;
using DiscoveryLogic.Analytics.Modules.Explorers;
using DiscoveryLogic.Analytics.Modules.LinkRules;
using DiscoveryLogic.Analytics.Modules.Nodes;
using DiscoveryLogic.Analytics.UI.Common.Events;
using DiscoveryLogic.Analytics.UI.Common.Wizard;
using DiscoveryLogic.Common.Utilities;
using DiscoveryLogic.Analytics.DataObjects;

namespace DiscoveryLogic.Analytics.Modules.Diagrams.NetworkDiagrams
{
    /// <summary>
    /// 
    /// </summary>
    public class FreeParticleCanvas : Canvas
    {
        #region events
        public delegate void OnVerticeSelected(Vertice v);

        public event OnVerticeSelected VerticeSelected;
        #endregion

        #region fields
        private Network _Network;
        private readonly DispatcherTimer _WorldTimer = new DispatcherTimer();
        private Point _OwnerWindowPosition;
        private Point _PrevAbsoluteMousePosition;
        private List<Vertice> _SelectedVertices = null;
        private int _ZIndex = 0;
        private int _Iteration = 0;
        #endregion

        #region props
        //private string _NetworkName;
        ///// <summary></summary>
        //public string NetworkName
        //{
        //    get
        //    {
        //        return this._NetworkName;
        //    }
        //    set
        //    {
        //        this._NetworkName = value;
        //    }
        //}

        //private NetworkVisual _NetVisual = NetworkVisual.Default;
        ///// <summary></summary>
        //public NetworkVisual NetVisual
        //{
        //    get
        //    {
        //        return this._NetVisual;
        //    }
        //    set
        //    {
        //        this._NetVisual = value;
        //    }
        //}

        //private NetworkExclusionSetting _ExSetting = NetworkExclusionSetting.Default;
        ///// <summary></summary>
        //public NetworkExclusionSetting ExSetting
        //{
        //    get
        //    {
        //        return this._ExSetting;
        //    }
        //    set
        //    {
        //        this._ExSetting = value;
        //    }
        //}

        //private NetworkInclusionSetting _InSetting = NetworkInclusionSetting.Default;
        ///// <summary></summary>
        //public NetworkInclusionSetting InSetting
        //{
        //    get
        //    {
        //        return this._InSetting;
        //    }
        //    set
        //    {
        //        this._InSetting = value;
        //    }
        //}

        //private List<Vertice> _Vertices;
        ///// <summary></summary>
        //public List<Vertice> Vertices
        //{
        //    get
        //    {
        //        return this._Vertices;
        //    }
        //    set
        //    {
        //        this._Vertices = value;
        //    }
        //}

        //private List<Edge> _Edges;
        ///// <summary></summary>
        //public List<Edge> Edges
        //{
        //    get
        //    {
        //        return this._Edges;
        //    }
        //    set
        //    {
        //        this._Edges = value;
        //    }
        //}

        private Graph _Graph;
        /// <summary></summary>
        public Graph Graph
        {
            get
            {
                return this._Graph;
            }
            set
            {
                this._Graph = value;
            }
        }

        public string NetworkName
        {
            get
            {
                if (this.Graph != null && this.Graph.Network != null)
                {
                    return this.Graph.Network.NetworkName;
                }
                return null;
            }
        }

        private double _AttractForce = 2.0;
        /// <summary></summary>
        public double AttractForce
        {
            get
            {
                return this._AttractForce;
            }
            set
            {
                this._AttractForce = value;
            }
        }

        private double _RepelForce = 20.0;
        /// <summary></summary>
        public double RepelForce
        {
            get
            {
                return this._RepelForce;
            }
            set
            {
                this._RepelForce = value;
            }
        }

        private IGraphRenderer _Renderer;
        /// <summary></summary>
        public IGraphRenderer Renderer
        {
            get
            {
                return this._Renderer;
            }
            set
            {
                this._Renderer = value;
            }
        }

        private IGraphMeasurer _Measurer;
        /// <summary></summary>
        public IGraphMeasurer Measurer
        {
            get
            {
                return this._Measurer;
            }
            set
            {
                this._Measurer = value;
            }
        }

        private Window _OwnerWindow;
        /// <summary></summary>
        public Window OwnerWindow
        {
            get
            {
                return this._OwnerWindow;
            }
            set
            {
                if (value != null)
                {
                    this._OwnerWindow = value;
                    this._OwnerWindowPosition = new Point(0, 0);
                    this._OwnerWindow.LocationChanged += new EventHandler(_OwnerWindow_LocationChanged);
                }
            }
        }

        void _OwnerWindow_LocationChanged(object sender, EventArgs e)
        {
            Vector deltaMovement = new Vector(this._OwnerWindowPosition.X - this._OwnerWindow.Left,
                this._OwnerWindowPosition.Y - this._OwnerWindow.Top);
            this._OwnerWindowPosition = new Point(this._OwnerWindow.Left, this._OwnerWindow.Top);
            foreach (Vertice v in this._Graph.Vertices.Values)
            {
                v.Position += deltaMovement;
            }
        }

        public List<Vertice> SelectedVertices
        {
            get
            {
                return this._SelectedVertices;
            }
        }
        #endregion

        #region scale
        private double scale = 1.0;
        public double Scale
        {
            get { return this.scale; }
            set
            {
                if (this.scale != value)
                {
                    scale = value;
                    this.LayoutTransform = new ScaleTransform(scale, scale);
                }
            }
        }
        #endregion

        #region ctor
        public FreeParticleCanvas()
        {
            //this._Vertices=new List<Vertice>();
            //this._Edges=new List<Edge>();
            this._Graph = null;
            this._WorldTimer.Interval = new TimeSpan(50);
            this._WorldTimer.Tick += new EventHandler(_WorldTimer_Tick);
        }

        public void InitGraph(Network network,
            NetworkVisual networkVisual,
            NetworkInclusionSetting inSettings,
            NetworkExclusionSetting exSettings)
        {
            this._Network = network;
            this._Graph = new Graph(network, networkVisual, inSettings, exSettings);
        }
        #endregion

        #region entity controls
        private void UpdateEntityControls()
        {
            this.Children.Clear();
            List<VerticeMeasure> verticeMeasures = VerticeMeasureManager.GetVerticeMeasures(this.NetworkName);
            Dictionary<EntityType, Dictionary<string, VerticeMeasure>> measures =
                VerticeMeasureManager.ToDictionary(verticeMeasures);
            VerticeMeasureRange range = VerticeMeasureManager.GetMeasureRanges(verticeMeasures);
            int w = (int)this.ActualWidth;
            int h = (int)this.ActualHeight;
            Random randGen = new Random();
            foreach (Vertice v in this.Graph.Vertices.Values)
            {
                EntityBase entity = v.Tag;
                VerticeMeasure vM = new VerticeMeasure();
                if (measures.ContainsKey(entity.EntityType) &&
                    measures[entity.EntityType].ContainsKey(entity.PKValue()))
                    vM = measures[entity.EntityType][entity.PKValue()];
                v.Control = this.CreateEntityControl(
                    entity, this.Graph.NetVisual,
                    vM, range);
                v.Position = new Vector(randGen.Next(w), randGen.Next(h));
            }
        }

        private EntityControlBase CreateEntityControl(
            EntityBase entity, NetworkVisual visual,
            VerticeMeasure measure, VerticeMeasureRange range)
        {
            EntityControlBase entityView = null;
            switch (entity.EntityType)
            {
                case EntityType.Persons:
                    entityView = new PersonNode(entity,
                        visual.EntityVisuals[EntityType.Persons],
                        false, measure, range);
                    ((PersonNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((PersonNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Publications:
                    entityView = new PubNode(entity,
                        visual.EntityVisuals[EntityType.Publications],
                        false, measure, range);
                    ((PubNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((PubNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Grants:
                    entityView = new GrantNode(entity,
                        visual.EntityVisuals[EntityType.Grants], false, measure, range);
                    ((GrantNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((GrantNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Organizations:
                    entityView = new OrgNode(entity,
                        visual.EntityVisuals[EntityType.Organizations],
                        false, measure, range);
                    ((OrgNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((OrgNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Document:
                    entityView =
                        new DocumentNode(entity,
                                         visual.EntityVisuals[EntityType.Document],
                                         false, measure, range);
                    ((DocumentNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((DocumentNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Subject:
                    entityView =
                        new SubjectNode(entity,
                                         visual.EntityVisuals[EntityType.Subject],
                                         false, measure, range);
                    ((SubjectNode)entityView).ExploreSelectedEntity += new OnExploreSelectedEntity(HandleExploreSelectedEntity);
                    ((SubjectNode)entityView).DefineNewRelation +=
                        new OnDefineNewRelationRuleFromNetworkEntity(HandleRuleDefinitionFromEntity);
                    break;
                case EntityType.Cluster:
                    entityView =
                        new ClusterNode(
                            entity, this._Network,
                            visual.EntityVisuals[EntityType.Cluster], false, measure, range);
                    break;
                case EntityType.Misc:
                    entityView =
                        new MiscNode(entity, visual.EntityVisuals[EntityType.Misc], false, measure, range);
                    break;
            }
            entityView.DataContext = entity;
            this.Children.Add(entityView);

            entityView.MouseEnter += new MouseEventHandler(this.Canvas_MouseEnter);
            entityView.MouseDown += new MouseButtonEventHandler(this.Canvas_MouseDown);
            entityView.MouseMove += new MouseEventHandler(this.Canvas_MouseMove);
            entityView.MouseUp += new MouseButtonEventHandler(this.Canvas_MouseUp);

            return entityView;
        }

        private void HandleExploreSelectedEntity(ExploreEntityEventArgs args)
        {
            if (!string.IsNullOrEmpty(this.NetworkName))
            {
                Network network = Network.Read(this.NetworkName);
                ExploreSelectedEntity explorer = new ExploreSelectedEntity(network, args.SrcEntity, args.TgtEntityType);
                PopupWindow dialog = new PopupWindow();
                dialog.Content = explorer;
                dialog.Show();
            }
        }

        private void HandleRuleDefinitionFromEntity(NewRuleFromNetworkEntityArgs args)
        {
            List<IWizardPageBase> wizPages = new List<IWizardPageBase>();
            LinkRuleNetworkSelectedEntity page1 = new LinkRuleNetworkSelectedEntity();
            LinkRuleSqlParameters page2 = new LinkRuleSqlParameters();
            LinkRuleTgtEntityFieldMappings page3 = new LinkRuleTgtEntityFieldMappings();
            LinkRuleDistanceCalculator page4 = new LinkRuleDistanceCalculator();

            page1.PrevPage = null;
            page1.NextPage = page2;

            page2.PrevPage = page1;
            page2.NextPage = page3;

            page3.PrevPage = page2;
            page3.NextPage = page4;

            page4.PrevPage = page3;
            page4.NextPage = null;

            wizPages.Add(page1);
            wizPages.Add(page2);
            wizPages.Add(page3);
            wizPages.Add(page4);
            EntityRelationRule rule =
                new EntityRelationRule(
                    "Link Rule", "/images/rule.png",
                    this.NetworkName,
                    args.Entity.EntityType,
                    EntityType.Grants,
                    args.Entity.PKValue());
            rule.SrcEntityType = args.Entity.EntityType;
            Dictionary<string, object> sharedVars = new Dictionary<string, object>();
            sharedVars.Add("LinkRule", rule);
            Wizard wiz = new Wizard(sharedVars, wizPages.ToArray(), page1);
            wiz.Finish += new Wizard.OnFinish(wizLinkRule_Finish);
            wiz.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            wiz.Show();
        }

        private void wizLinkRule_Finish(Dictionary<string, object> sharedVars)
        {
            EntityRelationRule rule = (EntityRelationRule)sharedVars["LinkRule"];
            RuleManager.Save(rule);
            MyData.ReadAllRules();
        }

        #endregion

        #region layout
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            foreach (UIElement element in this.InternalChildren)
            {
                double left = Canvas.GetLeft(element);
                double top = Canvas.GetTop(element);
                double x = double.IsNaN(left) ? 0 : left;
                double y = double.IsNaN(top) ? 0 : top;
                element.Arrange(new Rect(new Point(x, y), element.DesiredSize));
            }
            return arrangeSize;
        }

        protected override Size MeasureOverride(Size constraint)
        {
            Size size = new Size(double.PositiveInfinity, double.PositiveInfinity);
            foreach (UIElement element in this.InternalChildren)
            {
                element.Measure(size);
            }
            return new Size();
        }

        protected override void OnRender(System.Windows.Media.DrawingContext dc)
        {
            base.OnRender(dc);
            if (this.Renderer != null)
                this.Renderer.RenderEdges(dc,
                    this._Graph.NetVisual,
                    this._Graph.Vertices.Values.ToList(),
                    this._Graph.Edges.Values.ToList());
        }
        #endregion

        #region simulation
        public void StartSimulation()
        {
            if (this._WorldTimer.IsEnabled)
                this.StopSimulation();

            if (!this._WorldTimer.IsEnabled)
            {
                this.UpdateEntityControls();
                this._Iteration = 0;
                this._Renderer = new ForceDirected();
                this._Renderer.GraphRenderFinished += new OnFinishedGraphRendering(_Renderer_GraphRenderFinished);
                this._WorldTimer.IsEnabled = true;
            }
        }

        /// <summary>
        /// do not update entity control and entity positions 
        /// </summary>
        public void ContinueSimulation()
        {
            if (this._WorldTimer.IsEnabled)
                this.StopSimulation();

            if (!this._WorldTimer.IsEnabled)
            {
                this._Iteration = 0;
                this._Renderer = new ForceDirected();
                this._Renderer.GraphRenderFinished += new OnFinishedGraphRendering(_Renderer_GraphRenderFinished);
                this._WorldTimer.IsEnabled = true;
            }
        }

        void _Renderer_GraphRenderFinished()
        {
            this.StopSimulation();
        }

        public void StopSimulation()
        {
            if (_WorldTimer.IsEnabled)
                _WorldTimer.Stop();
            this._WorldTimer.IsEnabled = false;
            this._Iteration = 0;
        }

        void _WorldTimer_Tick(object sender, EventArgs e)
        {
            Rect constraintRect = new Rect(0, 0, this.ActualWidth, this.ActualHeight);
            lock (this._Graph)
            {
                this._Iteration++;

                if (this._Renderer != null)
                {
                    if (this._Renderer.IsStopped)
                    {
                        this.StopSimulation();
                    }
                    else
                    {
                        this._Renderer.UpdatePositions(
                            this._Graph.Vertices.Values.ToList(),
                            this._Graph.Edges.Values.ToList(),
                            this._Graph.NetVisual, constraintRect, this._Iteration,
                            this._AttractForce, this._RepelForce);
                    }
                }
                foreach (Vertice v in this._Graph.Vertices.Values)
                {
                    v.SetDisabled(this.IsDisabled(v,
                        this._Graph.InSetting,
                        this._Graph.ExSetting),
                        this._Graph.NetVisual.EntityVisuals[v.Tag.EntityType]);
                    //bool showLabel = this._Graph.NetVisual.EntityVisuals[v.Tag.EntityType].ShowLabelAll;
                    v.SnapControl();
                }
            }
            this.InvalidateVisual();
        }
        #endregion

        #region drag-drop
        public void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ButtonState == MouseButtonState.Released)
            {
                foreach (Vertice v in this._Graph.Vertices.Values)
                    v.CanMove = true;
            }
        }

        public void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point absolutePosition = Mouse.GetPosition(this);
                Rect constraintRect = new Rect(0, 0, this.ActualWidth, this.ActualHeight);
                foreach (Vertice v in this._Graph.Vertices.Values)
                {
                    if (v.Selected)
                    {
                        v.SetPosition(
                            new Vector(
                                v.Position.X +
                                (absolutePosition.X - this._PrevAbsoluteMousePosition.X),
                                v.Position.Y +
                                (absolutePosition.Y - this._PrevAbsoluteMousePosition.Y)),
                            constraintRect);
                        //bool showLabel = this._Graph.NetVisual.EntityVisuals[v.Tag.EntityType].ShowLabelAll;
                        v.SnapControl();
                    }
                }
                this._PrevAbsoluteMousePosition = absolutePosition;
                this.InvalidateVisual();
            }
        }

        public void Canvas_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                this._PrevAbsoluteMousePosition = Mouse.GetPosition(this);
                var verticeSelected = from particle in this._Graph.Vertices.Values
                                      where particle.Control == sender
                                      select particle;
                if (verticeSelected.Count() > 0)
                {
                    Vertice v = verticeSelected.First();
                    foreach (Vertice v2 in this._Graph.Vertices.Values)
                    {
                        if (v2 != v)
                        {
                            v2.SetSelected(false, this._Graph.NetVisual.EntityVisuals[v2.Tag.EntityType]);
                            v2.Highlighted = false;
                            v2.CanMove = true;
                            // v2.SnapControl();
                        }
                    }
                    v.SetSelected(true, this._Graph.NetVisual.EntityVisuals[v.Tag.EntityType]);
                    v.SnapControl();
                    List<Vertice> highlightedVertices = this._Graph.GetHighlightedVertices(v);
                    foreach(Vertice hV in highlightedVertices)
                    {
                        hV.Highlighted = true;
                    }
                    v.CanMove = false;
                    v.Control.SetValue(Canvas.ZIndexProperty, this._ZIndex++);
                    this._SelectedVertices = new List<Vertice>();
                    this._SelectedVertices.Add(v);

                    if (this.VerticeSelected != null)
                        this.VerticeSelected(v);
                    return;
                }
                else
                {
                    this._SelectedVertices = new List<Vertice>();
                    foreach (Vertice v in this._Graph.Vertices.Values)
                    {
                        v.SetSelected(false, this._Graph.NetVisual.EntityVisuals[v.Tag.EntityType]);
                        // v.SnapControl();
                    }
                }
            }
        }

        public void Canvas_MouseEnter(object sender, MouseEventArgs e)
        {
            (sender as Control).SetValue(Canvas.ZIndexProperty, this._ZIndex++);
        }
        #endregion

        #region selection
        public void SelectEntity(EntityBase entity)
        {
            this._SelectedVertices = new List<Vertice>();
            foreach (Vertice v2 in this._Graph.Vertices.Values)
            {
                if (v2.Tag.PKValue() == entity.PKValue() && v2.Tag.EntityType==entity.EntityType)
                {
                    v2.SetSelected(true, this._Graph.NetVisual.EntityVisuals[v2.Tag.EntityType]);
                    this._SelectedVertices.Add(v2);
                }
                else
                {
                    v2.SetSelected(false, this._Graph.NetVisual.EntityVisuals[v2.Tag.EntityType]);
                }
            }
            this.InvalidateVisual();
        }

        public void SelectEntities(List<EntityBase> entities)
        {
            Dictionary<EntityType,List<string>> selectedKeys=new Dictionary<EntityType, List<string>>();
            foreach(EntityBase entity in entities)
            {
                if(selectedKeys.ContainsKey(entity.EntityType))
                {
                    List<string> keys = selectedKeys[entity.EntityType];
                    keys.Add(entity.PKValue());
                    selectedKeys[entity.EntityType] = keys;
                }
                else
                {
                    List<string> keys=new List<string>();
                    keys.Add(entity.PKValue());
                    selectedKeys.Add(entity.EntityType, keys);
                }
            }
            this._SelectedVertices = new List<Vertice>();
            foreach (Vertice v2 in this._Graph.Vertices.Values)
            {
                if (selectedKeys.ContainsKey(v2.Tag.EntityType) && 
                    selectedKeys[v2.Tag.EntityType].Contains(v2.Tag.PKValue()))
                {
                    v2.SetSelected(true, this._Graph.NetVisual.EntityVisuals[v2.Tag.EntityType]);
                    this._SelectedVertices.Add(v2);
                }
                else
                {
                    v2.SetSelected(false, this._Graph.NetVisual.EntityVisuals[v2.Tag.EntityType]);
                }
            }
            this.InvalidateVisual();
        }

        public void SelectEntities(EntityType entityType)
        {
            this._Graph.RemoveAllEntityTypesExcept(
                entityType, 4, null, null);
            this.StartSimulation();
        }

        public void HighlightPrestigiousEntities()
        {
            List<EntityBase> entities = VerticeMeasureManager.GetPrestigiousEntities(this._Network.NetworkName);
            Dictionary<EntityType, List<string>> entityKeys = new Dictionary<EntityType, List<string>>();
            foreach (EntityBase entity in entities)
            {
                if (entityKeys.ContainsKey(entity.EntityType))
                {
                    List<string> keys = entityKeys[entity.EntityType];
                    keys.Add(entity.PKValue());
                    entityKeys[entity.EntityType] = keys;
                }
                else
                {
                    List<string> keys = new List<string>();
                    keys.Add(entity.PKValue());
                    entityKeys.Add(entity.EntityType, keys);
                }
            }
            if (entities != null && entities.Count > 0)
            {
                List<Vertice> vList = this._Graph.Vertices.Values.ToList();
                for (int i = 0; i < vList.Count; i++)
                {
                    EntityBase entity = vList[i].Tag;
                    if (entityKeys.ContainsKey(entity.EntityType) && entityKeys[entity.EntityType].Contains(entity.PKValue()))
                        vList[i].Highlighted = true;
                    else
                        vList[i].Highlighted = false;
                }
                this.ContinueSimulation();
            }
        }

        public void HighlightPopularEntities()
        {
            List<EntityBase> entities = VerticeMeasureManager.GetPopularEntities(this._Network.NetworkName);
            Dictionary<EntityType,List<string>> entityKeys=new Dictionary<EntityType, List<string>>();
            foreach(EntityBase entity in entities)
            {
                if(entityKeys.ContainsKey(entity.EntityType))
                {
                    List<string> keys = entityKeys[entity.EntityType];
                    keys.Add(entity.PKValue());
                    entityKeys[entity.EntityType] = keys;
                }
                else
                {
                    List<string> keys=new List<string>();
                    keys.Add(entity.PKValue());
                    entityKeys.Add(entity.EntityType, keys);
                }
            }
            if (entities != null && entities.Count > 0)
            {
                List<Vertice> vList = this._Graph.Vertices.Values.ToList();
                for (int i = 0; i < vList.Count; i++)
                {
                    EntityBase entity = vList[i].Tag;
                    if (entityKeys.ContainsKey(entity.EntityType) && entityKeys[entity.EntityType].Contains(entity.PKValue()))
                        vList[i].Highlighted = true;
                    else
                        vList[i].Highlighted = false;
                }
                this.ContinueSimulation();
            }
        }
        #endregion

        #region filter
        private bool IsDisabled(Vertice v, NetworkInclusionSetting inSetting, NetworkExclusionSetting exSetting)
        {
            if (!inSetting.IsEnabled && !exSetting.IsEnabled)
                return false;
            if (inSetting.IsEnabled)
            {
                if (inSetting.IncludeEntityTypes.Contains(v.Tag.EntityType))
                    return false;
            }
            if (exSetting.IsEnabled)
            {
                if (exSetting.ExcludeEntityTypes.Contains(v.Tag.EntityType))
                    return true;
            }
            return false;
        }
        #endregion
    }
}
